package com.moter.demo01.requirements.re_0905.question_meituan;

import java.util.Objects;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MoterThreadPoolExecutor {
    private Lock submitLock = new ReentrantLock();
    //    private Lock[] tasks;
//    private Condition[] conditions;
    private Worker[] workers;
    private volatile AtomicInteger state;//线程池状态
    private volatile AtomicInteger workCount;//任务数量
    //线程池状态
    private final int RUNNING = 0;//可接受任务状态
    private final int STOP = 1;//不接受任务，不出处理任务，中断所有处理的任务
    private final int SHUTDOWN = 2;//关闭状态，不接受新的任务，继续处理剩余的任务
    private final int TIDYING = 3;//所有任务都处理完成
    private final int TERMINATED = 4;//线程池最终关闭
    private AtomicInteger num;//线程编号
    //
    private int coreSize;//核心线程数
    //    private int maxSize;//最大线程数
    private BlockingQueue<Runnable> queue;//阻塞队列
    private Boolean rejectHandler;//拒绝策略 true不处理，false抛异常

    public MoterThreadPoolExecutor(int coreSize, BlockingQueue<Runnable> queue, Boolean rejectHandler) throws Exception {
        if (coreSize <= 0) {
            throw new Exception("线程池大小不能为0");
        }
        Objects.requireNonNull(queue, "队列不能为null");
        Objects.requireNonNull(rejectHandler, "拒绝策略不能为空");
        this.coreSize = coreSize;
        this.queue = queue;
        this.rejectHandler = rejectHandler;
        init();
    }

    public MoterThreadPoolExecutor(int coreSize, BlockingQueue<Runnable> queue) throws Exception {
        this(coreSize, queue, false);
    }

    /**
     * 初始化设置线程池状态和任务数量
     */
    private void init() {
        state = new AtomicInteger(0);
        workCount = new AtomicInteger(0);
        num = new AtomicInteger(0);
        workers = new Worker[coreSize];
        stopAll();
    }

    public void stopAll(){
        Thread stop = new Thread(() -> {
            while(true){
                if(state.get()==STOP) {
                    for (Worker worker : workers) {
                        worker.interrupt();
                    }
                    break;
                }
            }
        });
        stop.start();
    }
    /**
     * 提交任务
     *
     * @param task
     * @throws Exception
     */
    public void submit(Runnable task) throws Exception {
        Objects.requireNonNull(task,"任务为空");
        submitLock.lock();
        try {
            if (state.get() != RUNNING)//如果线程不能接受新任务抛出异常
                throw new Exception("无法接受新任务！");
            else if (workCount.get() < coreSize && num.get() < coreSize) {//如果核心线程有空余,且核心线程有空余线程没有启动起来
                addTask(task);//启动一个线程，
            } else if (queue.remainingCapacity() > 0) {//上面条件不满足，就加入队列
                queue.put(task);//加入队列
            } else {
                reject();//拒绝
            }
        } finally {
            submitLock.unlock();
        }
    }

    private void reject() throws Exception {
        if (!rejectHandler)
            throw new Exception("订单满了，请稍后添加！");
    }

    private void addTask(Runnable task) {
        workers[num.get()] = new Worker(task, num.get());
        System.out.println("外卖员"+workers[num.get()].number+"\t接单");
        new Thread(workers[num.get()]).start();
        num.getAndIncrement();
    }

    class Worker extends Thread {
        int number;//编号
        Runnable firstTask;

        public Worker(Runnable task, int i) {
            firstTask = task;
            this.number = i;
        }

        @Override
        public void run() {
            try {
                runWorker(this);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public void runWorker(Worker r) throws InterruptedException {
        Runnable w = r.firstTask;

        while (true) {
            while (w != null || (w = getTask()) != null) {//不断去队列拿取任务来执行
                System.out.println("外卖员"+r.number+"\t送单");

                w.run();
                System.out.println("外卖员"+r.number+"\t订单送达");
                w=null;
                workCount.decrementAndGet();
            }
            //如果线程池状态时中断  或者 是shutdown且队列没有任务，当前线程就执行完毕，推出。
            if (state.get() == STOP||(state.get()==SHUTDOWN&&queue.size()==0))
                break;
            Thread.yield();
        }
    }

    /**
     * 从队列获取任务
     * @return
     * @throws InterruptedException
     */
    public Runnable getTask() throws InterruptedException {
            return queue.poll(2, TimeUnit.SECONDS);
    }


    private void setStop() {
        state.set(STOP);
    }

    public void shutDown() {
        state.set(SHUTDOWN);
    }

    public void shutDownNow() {
        setStop();
    }
}
